home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / viewwrld / viewwrld.lha / viewworld / gr / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-21  |  31.5 KB  |  1,011 lines

  1. /* $Id: window.c,v 2.3 89/09/20 17:01:47 mbp Exp $
  2.  *
  3.  * window.c: window definitions and procedures
  4.  *
  5.  * This module is much too long and should really be broken up into
  6.  * smaller pieces.  But for now, just so I can pack everything up in
  7.  * shar files of 50K or smaller, this module consists of two pieces.
  8.  * This is part 1.  Part 2 is the file 'window2.c' and is #included
  9.  * below.
  10.  */
  11.  
  12. /************************************************************************
  13.  *        Copyright (C) 1989 by Mark B. Phillips                  *
  14.  *                                     *
  15.  * Permission to use, copy, modify, and distribute this software and    *
  16.  * its documentation for any purpose and without fee is hereby granted, *
  17.  * provided that the above copyright notice appear in all copies and    *
  18.  * that both that copyright notice and this permission notice appear in *
  19.  * supporting documentation, and that the name of Mark B. Phillips or   *
  20.  * the University of Maryland not be used in advertising or publicity   *
  21.  * pertaining to distribution of the software without specific, written *
  22.  * prior permission.  This software is provided "as is" without express *
  23.  * or implied warranty.                                                 *
  24.  ************************************************************************/
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <math.h>
  29. #include <malloc.h>
  30. #include "gr.h"
  31. #include "internal.h"
  32. #include "images.h"
  33. #include <sunwindow/defaults.h>
  34.  
  35. /************************************************************************
  36.  *      DECLARATIONS COMMON TO 2D VERSION AND 3D VERSION:             *
  37.  ************************************************************************/
  38.  
  39. #define MOUSE_MESSAGE_LENGTH            12
  40.  
  41. #define REGULAR_FONT_FILE "/usr/lib/fonts/fixedwidthfonts/cour.r.14"
  42. #define BOLD_FONT_FILE    "/usr/lib/fonts/fixedwidthfonts/cour.b.14"
  43.  
  44. Frame        GR_base_frame = NULL;
  45. Panel        GR_control_panel;
  46. Canvas        GR_canvas;
  47. Panel        GR_app_panel;
  48. Panel        GR_error_panel;
  49. Pixwin        *GR_canvas_pw;
  50.  
  51. /* Gadgets for application panel: */
  52. static Panel_item app_message[2], mouse_image[7], mouse_message[7];
  53. static int      mouse_image_x[7]   = {  2, 121, 239, 358, 477, 596, 714};
  54. static int      mouse_image_y[7]   = {  3,   3,   3,   3,   3,   3,   3};
  55. static int      mouse_message_x[7] = { 19, 137, 257, 375, 494, 613, 731};
  56. static int      mouse_message_y[7] = {  3,   3,   3,   3,   3,   3,   3};
  57. static int      app_message_x[4]   = { 10, 10};
  58. static int      app_message_y[4]   = { 27, 46};
  59. static Panel_item app_text;
  60. static Panel_item app_coordinate_message;
  61.  
  62. /* Gadgets for control panel: */
  63. static Panel_item quit_button, help_button, print_button=NULL;
  64.  
  65. /* Gadgets for error panel: */
  66. static Panel_item    error_message;
  67.  
  68. /* Button menus: */
  69. static Menu     help_button_menu, quit_button_menu, print_button_menu=NULL;
  70.  
  71. /* Application menu: */
  72. static Menu    app_menu;
  73. /* Procedure to do operations with app_menu on the fly */
  74. static Menu    app_menu_operation();
  75.  
  76. /* Notification procedures: */
  77. static int    quit_button_proc(), help_button_proc();
  78.  
  79. /* Event procedures: */
  80. static int    button_event_proc();
  81. static int    canvas_event_proc();
  82.  
  83. /* Default icon: */
  84. static short default_icon_image[] = {
  85. #include "images/gr.image"
  86. };
  87. DEFINE_ICON_FROM_IMAGE(default_icon, default_icon_image);
  88.  
  89. /* Miscellaneous Global Variables: */
  90. Pixfont        *GR_regular_font=NULL, *GR_bold_font=NULL;
  91. static int    error_message_present = 0;
  92. static Notify_value interposer();
  93. static int    register_interposer_window();
  94. static int    hold_error_message = 0;
  95. int        (*GR_redraw_proc)() = NULL;
  96.  
  97. /************************************************************************
  98.  *         DECLARATIONS SPECIFIC TO 2D VERSION:                   *
  99.  ************************************************************************/
  100.  
  101. #ifndef THREE_D
  102.  
  103. /* 2D version:
  104.  * Main frame (GR_base_frame) has 4 subwindows:
  105.  * ___________________________________________________________
  106.  * |                                          |              |
  107.  * |            application                   |   control    |
  108.  * |               panel                      |    panel     |
  109.  * |                                          |              |
  110.  * |---------------------------------------------------------|
  111.  * |                                                         |
  112.  * |                                                         |
  113.  * |                                                         |
  114.  * |                                                         |
  115.  * |                       canvas                            |
  116.  * |                                                         |
  117.  * |                                                         |
  118.  * |                                                         |
  119.  * |                                                         |
  120.  * |                                                         |
  121.  * |                                                         |
  122.  * |                                                         |
  123.  * |---------------------------------------------------------|
  124.  * |                     error panel                         |
  125.  * |---------------------------------------------------------|
  126.  */
  127.  
  128. int        GR_canvas_width  = 990;
  129. int        GR_canvas_height = 692;
  130.  
  131. #endif  /* end of 2D specific declarations */
  132.  
  133. /************************************************************************
  134.  *         DECLARATIONS SPECIFIC TO 3D VERSION:                   *
  135.  ************************************************************************/
  136.  
  137. #ifdef THREE_D
  138.  
  139. int        GR_canvas_width  = 835;
  140. int        GR_canvas_height = 692;
  141.  
  142. #define VIEW_CONTROL_PANEL_MESSAGE_LENGTH    15
  143.  
  144. #define VIEW_DATA_TEXT_LENGTH            30
  145.  
  146. #define ROTATION_ANGLE_SLIDER_DEFAULT        12
  147. #define ZOOM_FACTOR_SLIDER_DEFAULT        15
  148. #define PERSPECTIVE_FACTOR_SLIDER_DEFAULT    15
  149. #define PAN_FACTOR_DEFAULT            0.1
  150. #define DRAWING_MODE_DEFAULT            1
  151.  
  152. /* 3D version:
  153.  * Main frame (GR_base_frame) has 5 subwindows:
  154.  * ___________________________________________________________
  155.  * |                                          |              |
  156.  * |            application                   |   control    |
  157.  * |               panel                      |    panel     |
  158.  * |                                          |              |
  159.  * |---------------------------------------------------------|
  160.  * |                                          |              |
  161.  * |                                          |              |
  162.  * |                                          |              |
  163.  * |                                          |    view      |
  164.  * |              canvas                      |   control    |
  165.  * |                                          |    panel     |
  166.  * |                                          |              |
  167.  * |                                          |              |
  168.  * |                                          |              |
  169.  * |                                          |              |
  170.  * |                                          |              |
  171.  * |                                          |              |
  172.  * |---------------------------------------------------------|
  173.  * |                     error panel                         |
  174.  * |---------------------------------------------------------|
  175.  */
  176.  
  177. Panel        GR_view_control_panel;
  178.  
  179. /* Gadgets for view control panel: */
  180. static Panel_item horizontal_sweep_button, vertical_sweep_button, tilt_button;
  181. static Panel_item horizontal_pan_button, vertical_pan_button;
  182. static Panel_item perspective_button;
  183. static Panel_item zoom_button, redraw_button, reset_button;
  184. static Panel_item anim_button;
  185. static Panel_item view_data_button;
  186. static Panel_item rotation_angle_label, rotation_angle_value;
  187. static Panel_item rotation_angle_slider;
  188. static Panel_item zoom_factor_label, zoom_factor_value;
  189. static Panel_item zoom_factor_slider;
  190. static Panel_item perspective_factor_label, perspective_factor_value;
  191. static Panel_item perspective_factor_slider;
  192. static Panel_item drawing_mode_cycle;
  193. static Panel_item view_control_panel_message[4];
  194. static int      view_control_panel_message_x[4] = { 14,  14,  14,  14};
  195. static int      view_control_panel_message_y[4] = {550, 570, 590, 610};
  196.  
  197. /* View data subframe has only one panel in it, for displaying
  198.  * current viewing transformation data */
  199. static Frame        view_data_frame = NULL;
  200. static Panel        view_data_panel = NULL;
  201.  
  202. /* Gadgets for view data panel: */
  203. static Panel_item view_data_redraw_button, view_data_done_button;
  204. static Panel_item    eye_text, focus_text, up_text;
  205. static Panel_item    vpw_message, vpw_horizontal_text, vpw_vertical_text;
  206.  
  207. /* Button menus: */
  208. static Menu    horizontal_pan_button_menu;
  209. static Menu    horizontal_sweep_button_menu, perspective_button_menu;
  210. static Menu    anim_button_menu,reset_button_menu;
  211. static Menu    tilt_button_menu, vertical_pan_button_menu;
  212. static Menu    vertical_sweep_button_menu, view_data_button_menu;
  213. static Menu    zoom_button_menu;
  214. static Menu    redraw_button_menu;
  215.  
  216. /* Notification procedures: */
  217. static int    view_data_button_proc(), view_data_done_button_proc();
  218. static int    rotation_angle_slider_proc(), zoom_factor_slider_proc();
  219. static int    perspective_factor_slider_proc();
  220. static int    drawing_mode_cycle_proc();
  221. static int    view_button_proc();
  222. static int    anim_button_proc();
  223.  
  224. /* Miscellaneous procedures: */
  225. static char    *rotation_angle_string(), *zoom_factor_string();
  226. static char    *perspective_factor_string();
  227. extern int    gr_redraw();
  228.  
  229. #define SLIDER_VALUE_TO_ROTATION_ANGLE(x) ((double)(x))
  230. #define SLIDER_VALUE_TO_ZOOM_FACTOR(x) ((double)(x)/10.0)
  231. #define SLIDER_VALUE_TO_PERSPECTIVE_FACTOR(x) ((double)(x)/10.0)
  232.  
  233. int    GR_rotation_angle_slider_value = ROTATION_ANGLE_SLIDER_DEFAULT;
  234. int    GR_zoom_factor_slider_value = ZOOM_FACTOR_SLIDER_DEFAULT;
  235. int    GR_perspective_factor_slider_value = PERSPECTIVE_FACTOR_SLIDER_DEFAULT;
  236. double    GR_pan_factor = PAN_FACTOR_DEFAULT;
  237. int    GR_drawing_mode_value = DRAWING_MODE_DEFAULT;
  238.  
  239. #endif /* end of 3D specific declarations */
  240.  
  241. /************************************************************************
  242.  *    PUBLIC PROCEDURES COMMON TO 2D VERSION AND 3D VERSION:          *
  243.  ************************************************************************/
  244.  
  245. /*-----------------------------------------------------------------------
  246.  * Function:     GR_initialize_windows
  247.  * Description:  initializes the SunView window setup
  248.  * Arguments:     (none)
  249.  * Returns:      0 for success, 1 for failure
  250.  */
  251. int
  252. GR_initialize_windows(argc, argv)
  253.      int argc;
  254.      char **argv;
  255. {
  256.   int i;
  257.   char *nullargv=NULL;
  258.  
  259.   GR_regular_font = pf_open(REGULAR_FONT_FILE);
  260.   if (GR_regular_font==NULL) GR_regular_font = pf_default();
  261.   GR_bold_font = pf_open(BOLD_FONT_FILE);
  262.   if (GR_bold_font==NULL) GR_bold_font = pf_default();
  263.  
  264.   GR_base_frame =
  265.     window_create(NULL, FRAME,
  266.           WIN_X, 80,
  267.           WIN_Y, 30,
  268.           WIN_FONT, GR_regular_font,
  269.           FRAME_ICON, &default_icon,
  270.           FRAME_LABEL, "GR",
  271.           FRAME_ARGS, argc, (argc==0 ? &nullargv : argv),
  272.           0);
  273.   if (GR_base_frame == NULL) goto BAD_WINDOW_ERROR;
  274.   
  275.   GR_app_panel =
  276.     window_create(GR_base_frame, PANEL,
  277.           WIN_X, 0,
  278.           WIN_Y, 0,
  279.           WIN_WIDTH, 835,
  280.           WIN_HEIGHT, 80,
  281.           WIN_FONT, GR_regular_font,
  282.           0);
  283.   if (GR_app_panel == NULL) goto BAD_WINDOW_ERROR;
  284.  
  285.   for (i=0; i<2; ++i) {
  286.     app_message[i] =
  287.       panel_create_item(GR_app_panel, PANEL_MESSAGE, 
  288.             PANEL_ITEM_X, app_message_x[i],
  289.             PANEL_ITEM_Y, app_message_y[i],
  290.             PANEL_LABEL_STRING, "",
  291.             0);
  292.   }
  293.  
  294.   for (i=0; i<7; ++i) {
  295.     mouse_image[i] =
  296.       panel_create_item(GR_app_panel, PANEL_MESSAGE, 
  297.             PANEL_ITEM_X, mouse_image_x[i],
  298.             PANEL_ITEM_Y, mouse_image_y[i],
  299.             PANEL_LABEL_IMAGE, GR_mouse_image_pr_ptr(i),
  300.             PANEL_SHOW_ITEM, FALSE,
  301.             0);
  302.    mouse_message[i] =
  303.      panel_create_item(GR_app_panel, PANEL_MESSAGE, 
  304.                PANEL_ITEM_X, mouse_message_x[i],
  305.                PANEL_ITEM_Y, mouse_message_y[i],
  306.                PANEL_LABEL_STRING, "",
  307.                PANEL_LABEL_FONT, GR_bold_font,
  308.                0);
  309.  
  310.   }
  311.  
  312.   app_text =
  313.     panel_create_item(GR_app_panel, PANEL_TEXT,
  314.               PANEL_ITEM_X,        10,
  315.               PANEL_ITEM_Y,        64,
  316.               PANEL_LABEL_STRING,    ":",
  317.               PANEL_BLINK_CARET,    TRUE,
  318.               PANEL_VALUE_STORED_LENGTH,  GR_INPUT_TEXT_LENGTH,
  319.               PANEL_VALUE_DISPLAY_LENGTH, GR_INPUT_TEXT_LENGTH,
  320.               PANEL_SHOW_ITEM,        FALSE,
  321.               0);
  322.  
  323.   app_coordinate_message =
  324.     panel_create_item(GR_app_panel, PANEL_MESSAGE,
  325.               PANEL_ITEM_X,        10,
  326.               PANEL_ITEM_Y,        64,
  327.               PANEL_LABEL_STRING,    "",
  328.               0);
  329.  
  330.   GR_canvas =
  331.     window_create(GR_base_frame, CANVAS,
  332.           WIN_X, 0,
  333.           WIN_Y, 85,
  334.           WIN_WIDTH, GR_canvas_width,
  335.           WIN_HEIGHT, GR_canvas_height,
  336.           WIN_EVENT_PROC,    canvas_event_proc,
  337.           WIN_IGNORE_KBD_EVENTS, KBD_USE, KBD_DONE, 0,
  338.           WIN_CONSUME_KBD_EVENT, 27, /* <ESC> */
  339.           0);
  340.   if (GR_canvas == NULL) goto BAD_WINDOW_ERROR;
  341.   GR_canvas_pw = canvas_pixwin(GR_canvas);
  342.  
  343.   app_menu =
  344.     menu_create(MENU_GEN_PROC, app_menu_operation, 0);
  345.  
  346.   GR_control_panel =
  347.     window_create(GR_base_frame, PANEL,
  348.           WIN_X, 840,
  349.           WIN_Y, 0,
  350.           WIN_WIDTH, 150,
  351.           WIN_HEIGHT, 80,
  352.           WIN_FONT, GR_regular_font,
  353.           0);
  354.   if (GR_control_panel == NULL) goto BAD_WINDOW_ERROR;
  355.   
  356.   help_button =
  357.     panel_create_item(GR_control_panel, PANEL_BUTTON, 
  358.               PANEL_ITEM_X, 16,
  359.               PANEL_ITEM_Y, 16,
  360.               PANEL_LABEL_IMAGE, &help_pr,
  361.               PANEL_EVENT_PROC, button_event_proc,
  362.               PANEL_NOTIFY_PROC, help_button_proc,
  363.               0);
  364.   
  365.   help_button_menu =
  366.     menu_create(MENU_STRINGS, "Help", 0, 0);
  367.  
  368.   quit_button =
  369.     panel_create_item(GR_control_panel, PANEL_BUTTON, 
  370.               PANEL_ITEM_X, 86,
  371.               PANEL_ITEM_Y, 16,
  372.               PANEL_LABEL_IMAGE, &quit_pr,
  373.               PANEL_EVENT_PROC, button_event_proc,
  374.               PANEL_NOTIFY_PROC, quit_button_proc,
  375.               0);
  376.   quit_button_menu =
  377.     menu_create(MENU_STRINGS, "Exit Program", 0, 0);
  378.  
  379.   GR_error_panel =
  380.     window_create(GR_base_frame, PANEL,
  381.           WIN_X,      0,
  382.           WIN_BELOW,  GR_canvas,
  383.           WIN_FONT,   GR_bold_font,
  384.           WIN_WIDTH,  990,
  385.           WIN_HEIGHT, ATTR_ROW(1),
  386.           0);
  387.  
  388.   error_message =
  389.     panel_create_item(GR_error_panel, PANEL_MESSAGE,
  390.               WIN_X, 10,
  391.               WIN_Y, 5,
  392.               PANEL_LABEL_STRING, "",
  393.               0);
  394.  
  395. #ifdef THREE_D
  396.   if (initialize_view_control_panel() != 0) return(1);
  397.   if (GR_print_button(1, gr_redraw, "GR") != 0) return(1);
  398. #endif
  399.   
  400.   window_fit(GR_base_frame);
  401.   GR_register_interposer(GR_base_frame);
  402.   if (GR_initialize_confirmer() != 0) return(1);
  403.  
  404.   return(0);
  405.  
  406.   BAD_WINDOW_ERROR:
  407.   GR_error("Can't create any more windows !");
  408.   return(1);
  409. } /* End of GR_initialize_windows() */
  410.  
  411. /* -----------------------------------------------------------------------
  412.  * Function:     GR_show_app_message
  413.  * Description:  display a string in one of the 2 application panel
  414.  *            message lines
  415.  * Arguments IN: n: the number of the message line (0 or 1)
  416.  *          s: the string to be displayed
  417.  * Notes:        The message must be less than or equal to
  418.  *              GR_MESSAGE_LENGTH chars long (not including
  419.  *              the terminal null char).  If it is longer than this, on
  420.  *              the first GR_MESSAGE_LENGTH chars are
  421.  *              displayed, and 1 is returned.  Otherwise 0 is returned.
  422.  *
  423.  *         If s is the null string (not the NULL pointer!) the
  424.  *         message line is cleared.
  425.  */
  426. int
  427. GR_show_app_message(n,s)
  428.      int n;
  429.      char *s;
  430. {
  431.   if ( (n<0) || (n>1) || (s==NULL) ) return(1);
  432.   return( GR_show_message(app_message[n], s, GR_MESSAGE_LENGTH) );
  433. }
  434.  
  435. /* -----------------------------------------------------------------------
  436.  * Function:     GR_show_app_coordinate_message
  437.  * Description:  display a string in the application coordinate
  438.  *            message line
  439.  * Arguments IN: s: the string to be displayed
  440.  * Notes:        The message must be less than or equal to
  441.  *              GR_COORDINATE_MESSAGE_LENGTH chars long (not including
  442.  *              the terminal null char).  If it is longer than this, on
  443.  *              the first GR_COORDINATE_MESSAGE_LENGTH chars are
  444.  *              displayed, and 1 is returned.  Otherwise 0 is returned.
  445.  *
  446.  *         If s is the null string (not the NULL pointer!) the
  447.  *         message is cleared.
  448.  */
  449. int
  450. GR_show_app_coordinate_message(s)
  451.      char *s;
  452. {
  453.   if (s == NULL) return(1);
  454.   return( GR_show_message(app_coordinate_message, s,
  455.                GR_COORDINATE_MESSAGE_LENGTH) );
  456. }
  457.  
  458. /* -----------------------------------------------------------------------
  459.  * Function:     GR_show_mouse_message
  460.  * Description:  display a string in one of the 7 mouse button
  461.  *            message lines
  462.  * Arguments IN: n: the number of the mouse button (0,1,2,3,4,5,6)
  463.  *          s: the string to be displayed
  464.  * Returns:      0 for success, 1 otherwise
  465.  * Notes:        The message must be less than or equal to
  466.  *              MOUSE_MESSAGE_LENGTH chars long (not including
  467.  *              the terminal null char).  If it is longer than this, on
  468.  *              the first MOUSE_MESSAGE_LENGTH chars are
  469.  *              displayed, and 1 is returned.  Otherwise 0 is returned.
  470.  *
  471.  *         If s is the null string (not the NULL pointer!) the
  472.  *         n-th mouse message is cleared and the corresponding
  473.  *         image turned off.
  474.  */
  475. int
  476. GR_show_mouse_message(n,s)
  477.      int n;
  478.      char *s;
  479. {
  480.   if ( (n<0) || (n>6) || (s==NULL) ) return(1);
  481.   if (*s=='\0')
  482.     panel_set(mouse_image[n], PANEL_SHOW_ITEM, FALSE, 0);
  483.   else
  484.     panel_set(mouse_image[n], PANEL_SHOW_ITEM, TRUE, 0);
  485.   return( GR_show_message(mouse_message[n], s, MOUSE_MESSAGE_LENGTH) );
  486. }
  487.  
  488. /* -----------------------------------------------------------------------
  489.  * Function:     GR_show_error_message
  490.  * Description:  display a string in the error message panel
  491.  * Arguments IN: s: the string to be displayed
  492.  * Notes:        The message must be less than or equal to
  493.  *              GR_ERROR_MESSAGE_LENGTH chars long (not including
  494.  *              the terminal null char).  If it is longer than this, on
  495.  *              the first GR_ERROR_MESSAGE_LENGTH chars are
  496.  *              displayed, and 1 is returned.  Otherwise 0 is returned.
  497.  *
  498.  *         If s is the null string (not the NULL pointer!) the
  499.  *         message is cleared.
  500.  */
  501. int
  502. GR_show_error_message(s)
  503.      char *s;
  504. {
  505.   if (s == NULL) return(1);
  506.   return( GR_show_message(error_message, s, GR_ERROR_MESSAGE_LENGTH) );
  507. }
  508.  
  509. /*-----------------------------------------------------------------------
  510.  * Function:    GR_app_panel_get_string
  511.  * Description:    Get a string from the user
  512.  * Args  IN:    s: place to store string
  513.  * Notes:    The maximum allowable length of a string gotten by this
  514.  *        procedure is GR_INPUT_TEXT_LENGTH.
  515.  */
  516. int
  517. GR_app_panel_get_string(s)
  518.      char *s;
  519. {
  520.   Event event;
  521.   int done;
  522.   
  523.   /* Make sure all ascii events from canvas get passed to panel */
  524.   window_set(GR_canvas,
  525.          WIN_INPUT_DESIGNEE,
  526.              (int)window_get(GR_app_panel,WIN_DEVICE_NUMBER),
  527.          0);
  528.  
  529.   /* Enable display of text item in panel */
  530.   panel_set(app_text, PANEL_SHOW_ITEM, TRUE, 0 );
  531.  
  532.   /* Read panel events and update display of text item until
  533.    * user hits return key */
  534.   done = 0;
  535.   do {
  536.     window_read_event(GR_app_panel, &event);
  537.     if (event_is_ascii(&event))
  538.       done = process_ascii_event(&event);
  539.   } while (!done);
  540.  
  541.   /* Now copy text string to s, clear text item, and return
  542.    * to normal operation */
  543.   strcpy(s, (char*)panel_get(app_text,PANEL_VALUE) );
  544.   panel_set(app_text, PANEL_VALUE, "", 0 );
  545.   panel_set(app_text, PANEL_SHOW_ITEM, FALSE, 0 );
  546.   window_set(GR_canvas,
  547.          WIN_INPUT_DESIGNEE,
  548.              (int)window_get(GR_base_frame, WIN_DEVICE_NUMBER),
  549.          0 );
  550. }    
  551.  
  552. /* -----------------------------------------------------------------------
  553.  * Function:       GR_get_canvas_xy
  554.  * Description:       Get a point in canvas integer coords from the user
  555.  * Args     IN:       bmask: tells which buttons to recognize
  556.  *    OUT:       x,y: coords of point selected by user
  557.  *           button: button pressed by user
  558.  * Notes:       bmask should be a logical OR (|) of GR_LEFT,
  559.  *           GR_MIDDLE, GR_RIGHT, GR_SHIFT_LEFT, GR_SHIFT_MIDDLE,
  560.  *           GR_SHIFT_RIGHT, or GR_ESC.  It must include at least
  561.  *           one of these, or else an error occurrs.
  562.  */
  563. GR_get_canvas_xy(x,y,button,bmask)
  564.      int *x, *y;
  565.      gr_Button *button, bmask;
  566. {
  567.   Event event[1], *event_in_canvas_space;
  568.   int done;
  569.   Cursor cursor;
  570.   
  571.   /* Validate bmask value to make sure we can return */
  572.   if ( ! (  (bmask&GR_LEFT)
  573.           | (bmask&GR_MIDDLE)
  574.           | (bmask&GR_RIGHT)
  575.           | (bmask&GR_SHIFT_LEFT)
  576.           | (bmask&GR_SHIFT_MIDDLE)
  577.           | (bmask&GR_SHIFT_RIGHT)
  578.           | (bmask&GR_ESC) ) )
  579.     return(1);
  580.  
  581.   /* Change the cursor to a crosshair, and enable acceptance
  582.    * of ascii events for canvas so we can tell if user presses
  583.    * <ESC> key */
  584.   cursor = window_get( GR_canvas, WIN_CURSOR );
  585.   cursor_set(cursor,
  586.          CURSOR_SHOW_CURSOR,        FALSE,
  587.          CURSOR_SHOW_CROSSHAIRS,        TRUE,
  588.          CURSOR_CROSSHAIR_THICKNESS,    1,
  589.          CURSOR_CROSSHAIR_COLOR,        3,
  590.          CURSOR_CROSSHAIR_LENGTH,         CURSOR_TO_EDGE,
  591.          CURSOR_CROSSHAIR_OP,         PIX_SRC | PIX_DST,
  592.          0);
  593.   window_set(GR_canvas,
  594.          WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,
  595.          WIN_CURSOR, cursor,
  596.          0 );
  597.  
  598.   /* Read events in canvas until user presses appropriate key: */
  599.   do {
  600.     window_read_event(GR_canvas, event);
  601.  
  602.     /* Translate coords to canvas coords */
  603.     event_in_canvas_space=canvas_event(GR_canvas, event);
  604.     *x = event_x(event_in_canvas_space);
  605.     *y = event_y(event_in_canvas_space);
  606.  
  607.     /* If a coord display proc has been specified, call it */
  608.     if (GR_coordinate_display_proc!=NULL) {
  609.       GR_show_app_coordinate_message(
  610.          (*GR_coordinate_display_proc)(*x, *y));
  611.     }
  612.  
  613.     /* Now determine if we are done */
  614.     if (!event_is_down(event))
  615.       done = 0;
  616.     else
  617.       switch (event_id(event)) {
  618.       case MS_LEFT:
  619.     *button = event_shift_is_down(event) ?
  620.       GR_SHIFT_LEFT : GR_LEFT;
  621.     done = ( (*button&bmask)!=0 );
  622.     break;
  623.       case MS_MIDDLE:
  624.     *button = event_shift_is_down(event) ?
  625.       GR_SHIFT_MIDDLE : GR_MIDDLE;
  626.     done = ( (*button&bmask)!=0 );
  627.     break;
  628.       case MS_RIGHT:
  629.     *button = event_shift_is_down(event) ?
  630.       GR_SHIFT_RIGHT : GR_RIGHT;
  631.     done = ( (*button&bmask)!=0 );
  632.     break;
  633.       case 27: /* <ESC> */
  634.     *button = GR_ESC;
  635.     done = ( (*button&bmask)!=0 );
  636.     break;
  637.       default:
  638.     done = 0;
  639.     break;
  640.       }
  641.   }  while ( !done );
  642.  
  643.   /* Return the cursor to normal, and disable acceptance of
  644.    * ascii events in canvas: */
  645.   cursor = window_get( GR_canvas, WIN_CURSOR );
  646.   cursor_set(cursor,
  647.          CURSOR_SHOW_CURSOR,    TRUE,
  648.          CURSOR_SHOW_CROSSHAIRS,    FALSE,
  649.          0);
  650.   window_set(GR_canvas,
  651.          WIN_IGNORE_KBD_EVENT,    WIN_ASCII_EVENTS,
  652.          WIN_CURSOR,        cursor,
  653.          0);
  654.  
  655.   /* Clear the coordinate display, if we're using it */
  656.   if (GR_coordinate_display_proc!=NULL)
  657.       GR_show_app_coordinate_message("");
  658.  
  659.   return(0);
  660. }
  661.  
  662. /*-----------------------------------------------------------------------
  663.  * Function:    GR_print_button
  664.  * Description:    turn the "print" button in the control panel on or off
  665.  * Args  IN:    onoff: 1 to turn on, 0 to turn off
  666.  *        redraw_proc: procedure to be called to redraw screen
  667.  *        logo: string to use as program logo
  668.  * Notes:    redraw_proc specifies a procedure to be called when
  669.  *        generating PostScript.  It should redraw the entire
  670.  *        canvas, and should return 0 to indicate success, 1 to
  671.  *        indicate failure.  logo may be NULL if no logo is
  672.  *        desired.  Both redraw_proc and logo are used only when
  673.  *        onoff=1; their values are ignored when onoff=0.
  674.  */
  675. int
  676.   GR_print_button(onoff, redraw_proc, logo)
  677. int onoff;
  678. int (*redraw_proc)();
  679. char *logo;
  680. {
  681.   static int print_button_initialized = 0;
  682.  
  683.   if (onoff == 1) {        /* turn print button on */
  684.     if (redraw_proc == NULL) return(1);
  685.     GR_redraw_proc = redraw_proc;
  686.     GR_logo = logo;
  687.     if (print_button_initialized)
  688.       /* If already initialized, just make it visible */
  689.       panel_set(print_button, PANEL_SHOW_ITEM, TRUE, 0);
  690.     else {
  691.       /* Otherwize, initialize it */
  692.       print_button =
  693.     panel_create_item(GR_control_panel, PANEL_BUTTON, 
  694.               PANEL_ITEM_X, 51,
  695.               PANEL_ITEM_Y, 16,
  696.               PANEL_LABEL_IMAGE, &print_pr,
  697.               PANEL_EVENT_PROC, button_event_proc,
  698.               PANEL_NOTIFY_PROC, GR_show_ps_frame,
  699.               0);
  700.       print_button_menu =
  701.     menu_create(MENU_STRINGS, "Printer", 0, 0);
  702.       panel_set(help_button, PANEL_ITEM_X, 1, PANEL_ITEM_Y, 16, 0);
  703.       panel_set(quit_button, PANEL_ITEM_X, 101, PANEL_ITEM_Y, 16, 0);
  704.       panel_paint(print_button, PANEL_CLEAR);
  705.       print_button_initialized = 1;
  706.     }
  707.   }
  708.   else {            /* turn print button off */
  709.     if (print_button_initialized)
  710.       panel_set(print_button, PANEL_SHOW_ITEM, FALSE, 0);
  711.   }
  712.   return(0);
  713. }
  714.  
  715. /*-----------------------------------------------------------------------
  716.  * Function:    GR_error
  717.  * Description:    beep and display a message in the error panel
  718.  * Args  IN:    s: the message to display
  719.  * Notes:    s should be at most GR_ERROR_MESSAGE_LENGTH chars
  720.  */
  721. int
  722. GR_error(s)
  723.      char *s;
  724. {
  725.   int r;
  726.  
  727.   if (GR_window_open) {
  728.     window_bell(GR_base_frame);
  729.     r = GR_show_error_message(s);
  730.     error_message_present = 1;
  731.   }
  732.   else {
  733.     fprintf(stderr,"%s\n", s);
  734.     r = 0;
  735.   }
  736.   return(r);
  737. }
  738.  
  739. /*-----------------------------------------------------------------------
  740.  * Function:    GR_message
  741.  * Description:    display a message in the error panel
  742.  * Args  IN:    s: the message to display
  743.  * Notes:    s should be at most GR_ERROR_MESSAGE_LENGTH chars.
  744.  *        This is just like GR_error, but does not beep.
  745.  */
  746. int
  747. GR_message(s)
  748.      char *s;
  749. {
  750.   if (GR_window_open) {
  751.     GR_show_error_message(s);
  752.     error_message_present = 1;
  753.   }
  754.   else
  755.     fprintf(stderr,"%s\n", s);
  756. }
  757.  
  758. /*-----------------------------------------------------------------------
  759.  * Function:    GR_hold_error_message
  760.  * Description:    hold error message for specified number of mouse clicks
  761.  * Args  IN:    n: number of mouse clicks
  762.  * Notes:    Normally, the message in the error panel is cleared with
  763.  *        the first mouse click after it is displayed.  A call to
  764.  *        this procedure makes keeps it around for n additional
  765.  *        clicks.
  766.  */
  767. int
  768. GR_hold_error_message(n)
  769.      int n;
  770. {
  771.   hold_error_message = ( n >= 0 ? n : -n );
  772. }
  773.  
  774. /*-----------------------------------------------------------------------
  775.  * Function:    GR_release_error_message
  776.  * Description:    release an error message from being held
  777.  * Args:    (none)
  778.  * Notes:    This undoes the last call to GR_hold_error_message.  Any
  779.  *        error message will be cleared by the next mouse click.
  780.  */
  781. int
  782. GR_release_error_message()
  783. {
  784.   hold_error_message = 0;
  785. }
  786.  
  787. /*-----------------------------------------------------------------------
  788.  * Function:    GR_register_interposer
  789.  * Description:    register our interposer (procedure "interposer" above)
  790.  *          for every window in a window tree
  791.  * Args  IN:    frame: root of window tree
  792.  */
  793. int
  794. GR_register_interposer(frame)
  795.      Frame frame;
  796. {
  797.   GR_apply_function_all_windows(frame, register_interposer_window);
  798. }
  799.  
  800. /*-----------------------------------------------------------------------
  801.  * Function:    GR_mouse_image_pr_ptr
  802.  * Description:    get a pointer to a mouse button image Pixrect
  803.  * Args  IN:    n: number of mouse image (0,1,2,3,4,5,6)
  804.  * Returns:    the pointer to the Pixrect storing that mouse button image
  805.  */
  806. Pixrect *
  807. GR_mouse_image_pr_ptr(n)
  808. int n;
  809. {
  810.   switch (n) {
  811.   case 0: return(&lmouse_pr);
  812.   case 1: return(&mmouse_pr);
  813.   case 2: return(&rmouse_pr);
  814.   case 3: return(&lsmouse_pr);
  815.   case 4: return(&msmouse_pr);
  816.   case 5: return(&rsmouse_pr);
  817.   case 6: return(&esc_pr);
  818.   default: return(NULL);
  819.   }
  820. }
  821.  
  822. /*-----------------------------------------------------------------------
  823.  * Function:    GR_apply_function_all_windows
  824.  * Description:    apply a function to every window in a hierarchy
  825.  * Args  IN:    window: root of hierarchy
  826.  *        function: ptr to function to apply
  827.  * Returns:    nothing
  828.  * Notes:    calling syntax for function should be:
  829.  *            function(window)
  830.  *              Window window;
  831.  */
  832. int
  833. GR_apply_function_all_windows(window, function)
  834.      Window window;
  835.      int (*function)();
  836. {
  837.   Window subwindow;
  838.   int winno;
  839.  
  840.   if (window == NULL) return;
  841.  
  842.   /* Do it to this window */
  843.   (*function)(window);
  844.  
  845.   /* Now do it to all subwindows */
  846.   winno = 0;
  847.   do {
  848.     subwindow=(Window)window_get(window, FRAME_NTH_WINDOW, winno);
  849.     if (subwindow != NULL) {
  850.       if ((Window_type)(window_get(subwindow,WIN_TYPE)) == FRAME_TYPE)
  851.     GR_apply_function_all_windows(subwindow, function);
  852.       else
  853.     (*function)(subwindow);
  854.     }
  855.   ++winno;
  856.   } while (subwindow != NULL);
  857.  
  858.   return;
  859. }
  860. /*-----------------------------------------------------------------------
  861.  * Function:     GR_show_message
  862.  * Description:  display a string in a message item
  863.  * Arguments IN: item: handle of message item to display string in
  864.  *         s: the string to be displayed
  865.  *         m: maximum number of chars that can be displayed
  866.  *           in this message item
  867.  * Returns:      0 for success, 1 for failure
  868.  * Notes:        If s has more than max chars, only the first m are
  869.  *         displayed and 1 is returned.
  870.  */
  871. int
  872. GR_show_message(item, s, m)
  873.      Panel_item item;
  874.      char *s;
  875.      int m;
  876. {
  877.   int toobig;
  878.   char temp;
  879.  
  880.   if (toobig = (strlen(s)>m)) {
  881.     temp = s[m];
  882.     s[m] = '\0';
  883.     panel_set(item, PANEL_LABEL_STRING, s, 0);
  884.     s[m] = temp;
  885.   }
  886.   else
  887.     panel_set(item, PANEL_LABEL_STRING, s, 0);
  888.   return(toobig);
  889. }
  890.  
  891. /************************************************************************
  892.  *          PUBLIC PROCEDURES SPECIFIC TO 3D VERSION:                 *
  893.  ************************************************************************/
  894.  
  895. #ifdef THREE_D
  896.  
  897. /* -----------------------------------------------------------------------
  898.  * Function:     GR_show_view_control_panel_message
  899.  * Description:  display a string in one of the four view control
  900.  *            panel message lines
  901.  * Arguments IN: n: the number of the message line to use (0,1,2,3)
  902.  *          s: the string to be displayed
  903.  * Returns:      0 for success, 1 otherwise
  904.  * Notes:        The message must be less than or equal to
  905.  *              VIEW_CONTROL_PANEL_MESSAGE_LENGTH chars long (not including
  906.  *              the terminal null char).  If it is longer than this, on
  907.  *              the first VIEW_CONTROL_PANEL_MESSAGE_LENGTH chars are
  908.  *              displayed, and 1 is returned.  Otherwise 0 is returned.
  909.  */
  910. int
  911. GR_show_view_control_panel_message(n,s)
  912.      int n;
  913.      char *s;
  914. {
  915.   if ( (n<0) || (n>3) ) return(1);
  916.   return(
  917.      GR_show_message(view_control_panel_message[n], s,
  918.               VIEW_CONTROL_PANEL_MESSAGE_LENGTH)
  919.      );
  920. }
  921.  
  922. int
  923. GR_set_view_display(itemflag, values)
  924.      int itemflag;
  925.      double *values;
  926. {
  927.   char buf[VIEW_DATA_TEXT_LENGTH+1];
  928.   Panel_item item;
  929.  
  930.   switch (itemflag) {
  931.   case GR_EYE:
  932.     item = eye_text;
  933.     break;
  934.   case GR_FOCUS:
  935.     item = focus_text;
  936.     break;
  937.   case GR_UP:
  938.     item = up_text;
  939.     break;
  940.   case GR_VPW:
  941.     break;
  942.   default:
  943.     return(1);
  944.     break;
  945.   }
  946.  
  947.   if (itemflag == GR_VPW) {
  948.     sprintf(buf, "[%5.2f,%5.2f]", values[0], values[1]);
  949.     panel_set_value(vpw_horizontal_text, buf);
  950.     sprintf(buf, "[%5.2f,%5.2f]", values[2], values[3]);
  951.     panel_set_value(vpw_vertical_text, buf);
  952.   }
  953.   else {
  954.     sprintf(buf, "(%5.2f,%5.2f,%5.2f)", values[0], values[1], values[2]);
  955.     panel_set_value(item, buf);
  956.   }
  957.   return(0);
  958. }
  959.  
  960. int
  961. GR_get_view_display(itemflag, values)
  962.      int itemflag;
  963.      double *values;
  964. {
  965.   char buf[VIEW_DATA_TEXT_LENGTH+1], *c;
  966.   static char *seps = " \t,()[]{};";
  967.   Panel_item item;
  968.  
  969.   if (itemflag == GR_VPW) {
  970.     strcpy(buf, (char*)panel_get_value(vpw_horizontal_text));
  971.     if ((c=strtok(buf,seps)) == NULL) return(1);
  972.     values[0] = atof(c);
  973.     if ((c=strtok(NULL,seps)) == NULL) return(1);
  974.     values[1] = atof(c);
  975.     strcpy(buf, (char*)panel_get_value(vpw_vertical_text));
  976.     if ((c=strtok(buf,seps)) == NULL) return(1);
  977.     values[2] = atof(c);
  978.     if ((c=strtok(NULL,seps)) == NULL) return(1);
  979.     values[3] = atof(c);
  980.   }
  981.   else {
  982.     switch (itemflag) {
  983.     case GR_EYE:
  984.       item = eye_text;
  985.       break;
  986.     case GR_FOCUS:
  987.       item = focus_text;
  988.       break;
  989.     case GR_UP:
  990.       item = up_text;
  991.       break;
  992.     default:
  993.       return(1);
  994.       break;
  995.     }
  996.     strcpy(buf, (char*)panel_get_value(item));
  997.     if ((c=strtok(buf,seps)) == NULL) return(1);
  998.     values[0] = atof(c);
  999.     if ((c=strtok(NULL,seps)) == NULL) return(1);
  1000.     values[1] = atof(c);
  1001.     if ((c=strtok(NULL,seps)) == NULL) return(1);
  1002.     values[2] = atof(c);
  1003.   }
  1004.   return(0);
  1005. }
  1006.  
  1007.  
  1008. #endif  /* End of public 3D version procedures */
  1009.  
  1010. #include "window2.c"
  1011.